오라클과 연동
✒️ 2025-06-23 15:04 내용 수정
사전 준비
- project/src/main/webapp/META-INF 폴더에 context.xml 파일을 추가한다.
- JNDI 내용 참고.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
auth="Container"
name="jdbc/oracle_test"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
factory="org.apache.commons.dbcp.BasicDataSourceFactory"
url="jdbc:oracle:thin:@localhost:1521:xe"
username="계정명" password="비밀번호"
maxActive="20" maxIdle="10" maxWait="1"/>
</Context>
- project/src/main/webapp/WEB-INF 폴더에 commons-collections-3.2.1.jar, commons-dbcp-1.2.2.jar, commons-pool-1.4.jar, 버전에 맞는 ojdbc.jar 파일을 넣는다. (ojdbc8-23.3.0.23.09.jar 사용)
- https://commons.apache.org/collections/download_collections.cgi
- https://commons.apache.org/dbcp/download_dbcp.cgi
- https://commons.apache.org/pool/download_pool.cgi
- https://www.oracle.com/kr/database/technologies/appdev/jdbc-downloads.html
- 이미 존재하는 Oracle DB 계정을 이용하거나, 혹은 새 계정을 만든다.
- 작업 표시줄의 검색창에 Start Database를 입력해서 데이터베이스 창을 연다.
- 접속 확인을 위해
sqlplus 유저명/비밀번호를 입력하여 데이터베이스 접속을 확인한 후 exit; 으로 종료해준다.
model1
- 데이터를 처리하는 로직과 화면에 출력하는 로직을 모두 한 페이지에서 처리한다.
- Oracle DB의 HR 계정 테이블인 EMPLOYEES 테이블에서 사원의 이름, 성, 직업, 고용날짜, 급여, 부서번호를 조회해본다.
1. DTO 클래스
- 사원들의 속성을 저장할 클래스를 생성
- 클래스(Classes) 참고.
package DTO;
public class EmployeeDTO {
private String first_name;
private String last_name;
private String job_id;
private String hire_date;
private int salary;
private int department_id;
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getJob_id() {
return job_id;
}
public void setJob_id(String job_id) {
this.job_id = job_id;
}
public String getHire_date() {
return hire_date;
}
public void setHire_date(String hire_date) {
this.hire_date = hire_date;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getDepartment_id() {
return department_id;
}
public void setDepartment_id(int department_id) {
this.department_id = department_id;
}
}
2. JSP
- DB 연결과 웹 페이지 처리를 수행
- List 인터페이스, Block 요소#2. Table 태그 참고.
<%@page import="java.util.List"%>
<%@page import="java.util.ArrayList"%>
<%@page import="DTO.EmployeeDTO"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.Connection"%>
<%@page import="javax.sql.DataSource"%>
<%@page import="javax.naming.Context"%>
<%@page import="javax.naming.InitialContext"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
InitialContext ic = new InitialContext();
Context ctx = (Context)ic.lookup("java:comp/env");
DataSource ds = (DataSource)ctx.lookup("jdbc/oracle_test");
// 위에서 지정한 경로로 DB에 로그인 시도
Connection connec = ds.getConnection();
// 실행할 sql문 string
String sql = "SELECT * FROM EMPLOYEES";
// 문자열 형태의 sql문을 실제 query문으로 변경
PreparedStatement prestat = connec.prepareStatement(sql);
// query문 결과 저장
ResultSet rs = prestat.executeQuery();
// List에 EmployeeDTO 객체 저장
List<EmployeeDTO> list = new ArrayList<EmployeeDTO>();
while(rs.next()) {
EmployeeDTO dto = new EmployeeDTO();
dto.setFirst_name(rs.getString("FIRST_NAME"));
dto.setLast_name(rs.getString("LAST_NAME"));
dto.setJob_id(rs.getString("JOB_ID"));
dto.setHire_date(rs.getString("HIRE_DATE"));
dto.setSalary(rs.getInt("SALARY"));
dto.setDepartment_id(rs.getInt("DEPARTMENT_ID"));
list.add(dto);
}
rs.close();
prestat.close();
connec.close();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
<tr>
<th>이름</th>
<th>성</th>
<th>직업</th>
<th>고용날짜</th>
<th>급여</th>
<th>부서번호</th>
</tr>
<% for(int i = 0; i < list.size(); i++) { %>
<tr>
<td> <%= list.get(i).getFirst_name() %> </td>
<td> <%= list.get(i).getLast_name() %> </td>
<td> <%= list.get(i).getJob_id() %> </td>
<td> <%= list.get(i).getHire_date() %> </td>
<td> <%= list.get(i).getSalary() %> </td>
<td> <%= list.get(i).getDepartment_id() %> </td>
</tr>
<% } %>
</table>
</body>
</html>
- 데이터베이스의 내용을 조회하여 웹 페이지에서 확인할 수 있다.
DAO를 사용한 DB 연결
- model1에서 데이터 조회를 DAO를 사용하여 처리한다.
- DAO를 사용하면서 이번엔 HR 계정의 EMPLOYEES 테이블과 DEPARTMENTS 테이블을 이용해 웹 페이지에서 부서 이름을 누르면 해당 부서의 사원들 정보가 표시되도록 설정해본다.
- 데이터 객체#1. DB 접속용 클래스 생성, 데이터 객체#2. DTO 생성, 데이터 객체#3. DAO 생성 참고
- 흐름상 먼저 DB 연결을 위한 클래스를 생성하고, DTO 클래스를 생성한 다음, DAO 클래스를 생성한 뒤, 데이터를 웹 페이지에서 확인할 JSP를 작성한다.
1. 데이터베이스 연결 클래스
- 데이터베이스에 연결할 때 필요한 클래스를 singleton pattern을 따르도록 하여 중복해서 여러 번 객체를 만들지 않고도 데이터베이스에 접근할 수 있도록 만든다.
- Singleton Pattern 참고
package DTO;
import java.sql.Connection;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBConnection {
static DBConnection db = null;
DataSource ds;
// singleton pattern으로 생성
public static DBConnection getInstance() {
if(db == null) {
db = new DBConnection();
}
return db;
}
// 생성자에서 Context 객체와 DataSource 초기화
public DBConnection() {
try {
InitialContext ic = new InitialContext();
Context ctx = (Context)ic.lookup("java:comp/env");
ds = (DataSource)ctx.lookup("jdbc/oracle_test");
} catch (NamingException e) {
e.printStackTrace();
}
}
// 생성자에서 준비한 정보로 DB에 연결하여 Connection 객체 얻기
public Connection getConnection() {
Connection connec = null;
try {
connec = ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return connec;
}
}
2. DTO 생성
- DEPARTMENTS 테이블의 정보를 저장할 DTO
package DTO;
public class DepartmentDTO {
private int department_id;
private String department_name;
public int getDepartment_id() {
return department_id;
}
public void setDepartment_id(int department_id) {
this.department_id = department_id;
}
public String getDepartment_name() {
return department_name;
}
public void setDepartment_name(String department_name) {
this.department_name = department_name;
}
}
- EMPLOYEES 테이블의 정보를 저장할 DTO
package DTO;
public class EmployeeDTO {
private String first_name;
private String last_name;
private String job_id;
private String hire_date;
private int salary;
private int department_id;
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String first_name) {
this.first_name = first_name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public String getJob_id() {
return job_id;
}
public void setJob_id(String job_id) {
this.job_id = job_id;
}
public String getHire_date() {
return hire_date;
}
public void setHire_date(String hire_date) {
this.hire_date = hire_date;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getDepartment_id() {
return department_id;
}
public void setDepartment_id(int department_id) {
this.department_id = department_id;
}
}
3. DAO 생성
- DEPARTMENTS 테이블의 정보를 조회할 DAO 생성
- Resources/Java/예외 처리/예외 처리 참고.
- JSP에서 작성했을 때는 Servlet 변환 시 전체가 try-catch 처리가 되어 따로 작업하지 않았으나, 클래스 작성 시엔 try-catch를 따로 작성해야 한다.
package DAO;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import DTO.DBConnection;
import DTO.DepartmentDTO;
public class DepartmentDAO {
static DepartmentDAO dao;
// singletone pattern(lazy-initialization)
public static DepartmentDAO getInstance() {
if (dao == null) {
dao = new DepartmentDAO();
}
return dao;
}
// DB 조회 결과를 List에 저장하여 반환
public List<DepartmentDTO> selectList() {
List<DepartmentDTO> list = new ArrayList<>();
Connection connec = null;
PreparedStatement prestat = null;
ResultSet rs = null;
String sql = "SELECT * FROM DEPARTMENTS";
try {
// 1. Connection 얻어오기
connec = DBConnection.getInstance().getConnection();
// 2. sql문 얻어오기
prestat = connec.prepareStatement(sql);
// 3. sql문 실행 결과 처리 객체 얻어오기
rs = prestat.executeQuery();
// 4. DepartmentDTO 필드에 속성을 저장하고 List에 저장하기
while(rs.next()) {
DepartmentDTO dto = new DepartmentDTO();
dto.setDepartment_id(rs.getInt("DEPARTMENT_ID"));
dto.setDepartment_name(rs.getString("DEPARTMENT_NAME"));
list.add(dto);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 항상 DB에 연관된 객체는 사용 후 닫아주기
// 생성했던 역순으로 닫기
try {
if (rs != null) {
rs.close();
}
if (prestat != null) {
prestat.close();
}
if (connec != null) {
connec.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return list;
}
}
- EMPLOYEES 테이블의 정보를 조회할 DAO 생성
- 여기서 sql은 department_list.jsp에서 보낸 정보에 따라 특정 조건을 만족하는 사원만 검색하기 위해 Setter를 이용해 employee_list.jsp에서 수정할 예정이다.
package DAO;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import DTO.DBConnection;
import DTO.EmployeeDTO;
public class EmployeeDAO {
static EmployeeDAO dao;
// singletone pattern(lazy-initialization)
public static EmployeeDAO getInstance() {
if (dao == null) {
dao = new EmployeeDAO();
}
return dao;
}
String sql = "SELECT * FROM EMPLOYEES";
// DB 조회 결과를 List에 저장하여 반환
public List<EmployeeDTO> selectList() {
List<EmployeeDTO> list = new ArrayList<>();
Connection connec = null;
PreparedStatement prestat = null;
ResultSet rs = null;
try {
// 1. Connection 얻어오기
connec = DBConnection.getInstance().getConnection();
// 2. sql문 얻어오기
prestat = connec.prepareStatement(sql);
// 3. sql문 실행 결과 처리 객체 얻어오기
rs = prestat.executeQuery();
// 4. EmployeeDTO 필드에 속성을 저장하고 List에 저장하기
while(rs.next()) {
EmployeeDTO dto = new EmployeeDTO();
dto.setFirst_name(rs.getString("FIRST_NAME"));
dto.setLast_name(rs.getString("LAST_NAME"));
dto.setJob_id(rs.getString("JOB_ID"));
dto.setHire_date(rs.getString("HIRE_DATE"));
dto.setSalary(rs.getInt("SALARY"));
dto.setDepartment_id(rs.getInt("DEPARTMENT_ID"));
list.add(dto);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 항상 DB에 연관된 객체는 사용 후 닫아주기
// 생성했던 역순으로 닫기
try {
if (rs != null) {
rs.close();
}
if (prestat != null) {
prestat.close();
}
if (connec != null) {
connec.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return list;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
}
4. JSP 생성
- DEPARTMENTS 테이블 정보를 볼 웹페이지 생성
- form 태그와 input 태그를 이용해 부서이름을 누르면 employee_list.jsp로 정보를 넘겨준다.
- a 태그에서 \javascript:send(data) 메소드를 사용하여 하이퍼링크를 누르면 form 태그의 정보를 넘겨준다.
- 자주 사용하는 방법은 아니라고 한다.
- hidden 타입의 input 태그를 만들어 input 태그의 value에 data를 넣어 form을 get 방식으로 employee_list.jsp에 데이터를 넘겨준다.
- Block 요소#4. form 태그, Inline 요소#4. input 태그 참고.
<%@page import="DTO.DepartmentDTO"%>
<%@page import="java.util.List"%>
<%@page import="DAO.DepartmentDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
<!-- DepartmentDAO 객체로 데이터베이스의 DEPARTMENTS 테이블 정보 조회 -->
DepartmentDAO dao = DepartmentDAO.getInstance();
List<DepartmentDTO> list = dao.selectList();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
<!-- 정보를 전송하기 위한 메소드 -->
function send(data) {
let f = document.dept;
var deptid = f.deptid;
deptid.value = data;
f.method = "GET";
f.action = "employee_list.jsp";
f.submit();
}
</script>
</head>
<body>
<form name="dept">
<table border="1">
<tr>
<th>부서번호</th>
<th>부서이름</th>
</tr>
<% for(int i = 0; i < list.size(); i++) { %>
<tr>
<td> <%= list.get(i).getDepartment_id() %> </td>
<!-- a 태그를 이용하여 메소드 호출 및 데이터 파라미터 전달-->
<td> <a href="javascript:send('<%= list.get(i).getDepartment_id() %>');"><%= list.get(i).getDepartment_name() %></a> </td>
</tr>
<% } %>
</table>
<!-- input 태그의 value에 데이터를 저장하기 위해 hidden 타입으로 설정 -->
<input type="hidden" name="deptid">
</form>
</body>
</html>
- EMPLOYEES 테이블 정보를 볼 웹페이지 생성
- department_list.jsp에서 보낸 내용을 request.getParameter(data) 메소드로 수신한다.
- 수신한 내용으로 EmployeeDAO 클래스의 String sql 내용을 Setter로 수정하고, selectList() 메소드로 조회한다.
<%@page import="DTO.EmployeeDTO"%>
<%@page import="java.util.List"%>
<%@page import="DAO.EmployeeDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// department_list.jsp에서 보낸 deptid
// request로 보낸 내용은 String이므로 형변환
int deptid = Integer.parseInt(request.getParameter("deptid"));
EmployeeDAO dao = EmployeeDAO.getInstance();
// department_list.jsp에서 보낸 deptid 내용으로 EmployeeDAO의 sql 수정
dao.setSql("SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = " + deptid);
List<EmployeeDTO> list = dao.selectList();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="department_list.jsp">뒤로 돌아가기</a>
<table border="1">
<tr>
<th>이름</th>
<th>성</th>
<th>직업</th>
<th>고용날짜</th>
<th>급여</th>
<th>부서번호</th>
</tr>
<% for(int i = 0; i < list.size(); i++) { %>
<tr>
<td> <%= list.get(i).getFirst_name() %> </td>
<td> <%= list.get(i).getLast_name() %> </td>
<td> <%= list.get(i).getJob_id() %> </td>
<td> <%= list.get(i).getHire_date() %> </td>
<td> <%= list.get(i).getSalary() %> </td>
<td> <%= list.get(i).getDepartment_id() %> </td>
</tr>
<% } %>
</table>
</body>
</html>
-
department_list.jsp를 통해 Oracle DB의 HR 계정 테이블 중 DEPARTMENTS 테이블의 내용을 확인할 수 있다.
-
위 웹 페이지에서 부서 이름을 누르면 해당 부서에 속한 사원의 정보를 볼 수 있다.
- URI에서 query string을 보면 deptid가 department_list.jsp에서 employee_list.jsp로 잘 넘어온 것을 확인할 수 있다.
- URI에서 query string을 보면 deptid가 department_list.jsp에서 employee_list.jsp로 잘 넘어온 것을 확인할 수 있다.